%%%-------------------------------------------------------------------
%%% @author mirahs(2892727493@qq.com)
%%% @doc
%%%     角色定时器处理
%%% @end
%%%-------------------------------------------------------------------
-module(role_timer).

-export([
    set_timer/5
    ,set_timer/2
    ,del_timer/2
    ,handle_timer/2
]).

-include("common.hrl").
-include("role.hrl").
-include("timer.hrl").


%% debug_log
-define(timer_debug(S1, S2), ok).
%-define(timer_debug(S1, S2), ?DEBUG(S1, S2)).


%%%===================================================================
%%% API functions
%%%===================================================================

set_timer(_, Timeout, _, _, Role) when Timeout =< 0; Timeout > 2600000000 -> Role;
set_timer(TimingId, Timeout, MFA, Count, Role) ->
    set_timer(new_timer(TimingId, Timeout, MFA, Count), Role).

set_timer(Timing = #timer{id = TimingId, timeout = Timeout, mfa = MFA, count = _Count}, Role = #role{name = _Name, pid = RolePid, timer = Timers}) ->
    case lists:keyfind(TimingId, #timer.id, Timers) of
        T = #timer{id = TimingId, ref = Ref, mfa = MFA} ->
            ?timer_debug("角色[NAME:~s]定时器已经存在[TimingID:~w]，重新设置", [_Name, TimingId]),
            case erlang:read_timer(Ref) of
                false ->
                    NewRef = start_timer(Timeout, RolePid, TimingId),
                    Role#role{timer = lists:keyreplace(TimingId, #timer.id, Timers, T#timer{ref = NewRef, num = 0})};
                _Remain ->
                    ?ERR("角色[NAME:~s]定时器已经存在[TimingID:~w]且未超时[Remain:~w]，忽略处理", [_Name, TimingId, _Remain]),
                    Role
            end;
        false ->
            ?timer_debug("设置角色定时器[NAME:~s TimingID:~w, Timeout:~w, count=~w]", [_Name, TimingId, Timeout, _Count]),
            NewRef1 = start_timer(Timeout, RolePid, TimingId),
            Role#role{timer = [Timing#timer{ref = NewRef1} | Timers]};
        _Other ->
            ?ERR("角色定时器设置异常[TimingID:~w, Timer:~w], 直接忽略", [TimingId, _Other]),
            Role
    end.

del_timer(TimingId, Role = #role{name = _Name, timer = Timers}) ->
    case lists:keyfind(TimingId, #timer.id, Timers) of
        #timer{ref = Ref, timeout = Timeout} ->
            Remain = case erlang:cancel_timer(Ref) of
                         false -> Timeout;
                         Time -> Time
                     end,
            ?timer_debug("删除定时器[Role:~s, TimingID:~w, Timeout:~w, Remain:~w]", [_Name, TimingId, Timeout, Remain]),
            {ok, {Timeout, Remain}, Role#role{timer = lists:keydelete(TimingId, #timer.id, Timers)}};
        false ->
            ?timer_debug("没找到要删除的定时器[Role:~s, TimingID:~w]", [_Name, TimingId]),
            false
    end.

handle_timer(State = #role{timer = Timers}, TimerId) ->
    %% ?timer_debug("处理timer: ~w", [TimerId]),
    case lists:keyfind(TimerId, #timer.id, Timers) of
        false ->
            ?timer_debug("定时器回调处理循环时找不到TimingId:~w", [TimerId]),
            {ok};
        T = #timer{mfa = {M, F, A}} ->
            {ok, {M, F, A}, do_handle_timer(State, T)}
    end.


%%%===================================================================
%%% Internal functions
%%%===================================================================

new_timer(Id, Timeout, {M, F, A}, Count) ->
    #timer{
        id = Id
        ,timeout = Timeout
        ,mfa = {M, F, A}
        ,count = Count
        ,num = 0
    }.

do_handle_timer(State = #role{pid = Pid, timer = Timers}, T = #timer{id = TimingId, timeout = Timeout, count = 0}) ->
    NewRef = start_timer(Timeout, Pid, TimingId),
    State#role{timer = lists:keyreplace(TimingId, #timer.id, Timers, T#timer{ref = NewRef})};
do_handle_timer(State = #role{pid = Pid, timer = Timers}, T = #timer{id = TimingId, timeout = Timeout, count = Count, num = Num}) when Count > 0 ->
    case Num + 1 >= Count of
        true ->
            State#role{timer = lists:keydelete(TimingId, #timer.id, Timers)};
        false ->
            NewRef = start_timer(Timeout, Pid, TimingId),
            State#role{timer = lists:keyreplace(TimingId, #timer.id, Timers, T#timer{ref = NewRef, num = Num + 1})}
    end;
do_handle_timer(State, _T) ->
    ?ERR("角色定时器处理异常[Role:~s, TimerID:~w]", [State, _T]),
    State.

start_timer(Timeout, RolePid, TimingId) ->
    erlang:send_after(Timeout, RolePid, {timer, TimingId}).
